Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

7장. Low Latency를 가능하게 하는 데이터 구조 — CMAF

7.1 왜 데이터 구조까지 바뀌어야 했는가

6장에서 LL-HLS의 핵심은 “기다림을 줄이는 것“이었다.

  • segment를 part로 나누고
  • part는 만들어지는 즉시 전달
  • polling 대신 blocking reload

이 중 가장 본질적인 변화는 이것이다.

완성된 파일이 아니라, 생성 중인 데이터를 전달한다

여기서 문제가 생긴다.

기존 HLS에서 사용하던 .ts 구조로는 이걸 깔끔하게 구현할 수 없다.

동작 방식의 변화는 데이터 형식의 변화를 요구한다.


7.2 TS는 왜 중간 전송이 어려운가

4장에서 이미 다뤘지만 다시 떠올려보자.

TS는 본래 방송 송출을 위해 만들어진 포맷이다.

  • 188바이트 패킷이 끝없이 이어진다
  • 한 프레임이 여러 패킷에 분산된다
  • 디코딩 정보(PAT/PMT)는 주기적으로 반복된다
[PAT][PMT][V][V][A][V][A][PAT][PMT][V][V]...

이 구조에서 다음 시도를 한다고 해보자.

“지금 0.4초까지 만든 데이터를 일단 보내자”

문제는 이렇다.

  • 마지막 프레임이 잘려 있을 수 있다
  • PES 헤더와 본문이 분리되어 있을 수 있다
  • PAT/PMT가 아직 이 부분에 안 왔을 수 있다

결국 받는 쪽은 디코딩에 실패한다.

그래서 TS에서는 완성된 segment 단위로만 안전하게 전송할 수 있었다.


7.3 fMP4가 LL-HLS를 가능하게 한 이유

4장에서 본 fMP4 구조를 다시 보자.

init.mp4  (ftyp + moov + mvex)
  ↑ 초기 정보

moof + mdat   ← fragment 1
moof + mdat   ← fragment 2
moof + mdat   ← fragment 3
...

여기서 중요한 포인트가 두 개 있다.


7.3.1 moof + mdat의 독립성

moof + mdat 하나의 짝은 그 자체로 완성된 작은 영상이다.

각 fragment에는:

  • 어떤 시간 구간인지 (tfdt)
  • 몇 개의 샘플(프레임)이 들어있는지 (trun)
  • 각 샘플의 크기와 오프셋
  • 코덱은 init에서 받았으므로 별도 정보 불필요

즉 앞 fragment를 몰라도 이 짝만으로 재생이 가능하다.

이 구조 때문에 다음이 가능해진다.

  • 전체 segment를 기다릴 필요 없음
  • fragment 하나가 완성되면 즉시 전송 가능
  • 받는 쪽도 받자마자 즉시 디코딩

7.3.2 init.mp4와 본체의 분리

fMP4는 초기 정보와 본체를 분리한다.

init.mp4 (한 번만 다운로드)
  ↓
  moof + mdat
  moof + mdat
  moof + mdat   ← 계속 추가

이 분리가 가져오는 효과:

  • segment마다 코덱 정보 반복 불필요
  • fragment 크기가 작아진다
  • 새 segment를 처음부터 받아도 init만 있으면 즉시 재생

이건 HLS의 EXT-X-MAP 태그가 가리키는 것과 정확히 일치한다.


TS vs fMP4 한 줄 요약

TS: 전체가 하나의 흐름 fMP4: 완전한 조각들이 이어진 구조

이 차이 덕분에 “생성 중 전송“이 자연스럽게 가능해진다.


7.4 fMP4만으로 부족했던 이유

여기까지 보면 fMP4로 모든 문제가 풀린 것처럼 보인다.

하지만 실제 서비스에서는 또 다른 문제가 생긴다.


표준화의 부재

각자 방식대로 쪼개기 시작하면 호환이 깨진다.

  • 어떤 인코더는 0.5초 단위
  • 어떤 인코더는 1초 단위
  • 어떤 인코더는 비트레이트가 다름

게다가 같은 fMP4여도

  • HLS용 fMP4
  • DASH용 fMP4

가 서로 미묘하게 달랐다.

예:

항목HLS fMP4DASH fMP4
박스 순서약간 다름약간 다름
brand 코드mp42iso6
메타데이터 위치차이 있음차이 있음

이 차이 때문에

하나의 fMP4 파일을 두 프로토콜에서 그대로 쓸 수 없었다.

서비스 입장에서는 같은 영상을 두 번 인코딩하고 두 번 저장해야 했다.

저장 비용과 CDN 비용이 두 배가 된다.


7.5 CMAF가 해결한 것 ①: 쪼개는 단위

이 문제를 해결하기 위해 등장한 것이 CMAF (Common Media Application Format)이다.

ISO 표준으로 2018년 발표되었다.

CMAF는 새로운 구조가 아니다.

CMAF는 fMP4를 어떻게 사용할지 정의한 규칙이다.

세 가지를 표준화한다.

  • 쪼개는 단위
  • 전송 방식
  • 호환성

데이터의 계층

CMAF는 데이터를 다음 계층으로 정의한다.

Track       (예: 1080p 비디오 트랙)
  └── Segment       (플레이어가 인식하는 단위)
        └── Fragment    (내부 논리 단위)
              └── Chunk       (실제 전송 단위)
단위역할
SegmentURL로 요청되는 단위
Fragmentmoof+mdat 한 쌍
Chunk가장 작은 전송 단위

용어 정리 (헷갈리는 부분)

HLS 용어CMAF 용어
PartChunk
SegmentSegment
(없음)Fragment

HLS의 Part와 CMAF의 Chunk는 사실상 같은 것이다. 서로 다른 표준이라 이름이 다를 뿐이다.


핵심 규칙

CMAF는 chunk에 강한 제약을 둔다.

각 chunk는 독립적으로 디코딩 가능해야 한다.

즉 chunk는 자기 안에 완전한 moof + mdat 쌍을 포함한다.

이 규칙 덕분에 중간부터 받아도 재생이 가능하다.


7.6 CMAF가 해결한 것 ②: 전송 방식

과거에는 fMP4를 써도 segment 전체를 다 만든 뒤 보내는 경우가 많았다.

CMAF는 이렇게 정의한다.

chunk가 만들어지면 즉시 전송해야 한다.

이때 사용하는 방식이 6장에서 본 HTTP Chunked Transfer Encoding이다.

[CMAF chunk 1 만들어짐] → 즉시 chunk 응답
[CMAF chunk 2 만들어짐] → 즉시 chunk 응답
[CMAF chunk 3 만들어짐] → 즉시 chunk 응답
...
[Segment 종료]         → 응답 종료

데이터가 파일처럼 한 번에 내려오는 것이 아니라 스트림처럼 계속 흘러오게 된다.


LL-HLS와의 관계

LL-HLS는 CMAF의 chunk를 Part 단위로 m3u8에 노출한다.

#EXT-X-PART:DURATION=0.200,URI="seg100.0.m4s"
#EXT-X-PART:DURATION=0.200,URI="seg100.1.m4s"

같은 chunk를 DASH 측에서는 다른 방식으로 노출한다. (LL-DASH의 availabilityTimeOffset)

데이터는 같고, 안내 방식만 다르다.


7.7 CMAF가 해결한 것 ③: 호환성

가장 큰 효과는 여기서 나온다.

CMAF는 fMP4 구조를 HLS와 DASH가 공유하도록 통일한다.

[ CMAF segment ]
       ↓
   ┌───┴────┐
HLS     DASH
용     용

동일한 파일이 두 프로토콜에서 그대로 재생 가능하다.


서비스 입장에서의 이득

CMAF 이전:

원본 → HLS용 fMP4 (1080p, 720p, 480p)
     → DASH용 fMP4 (1080p, 720p, 480p)
     [저장 2배, CDN 2배]

CMAF 이후:

원본 → CMAF (1080p, 720p, 480p)
       ↑ 한 벌만 생성
     → HLS playlist (m3u8)
     → DASH playlist (MPD)
       ↑ 매니페스트만 두 종류

저장 비용과 CDN 비용이 거의 절반으로 줄어든다.


7.8 Common Encryption (CENC)과 CMAF

CMAF의 또 다른 중요한 측면은 암호화 호환성이다.

DRM은 9장에서 자세히 다루지만, 여기서는 CMAF와의 관계만 짚는다.


과거의 문제

DRM 시스템마다 암호화 방식이 달랐다.

시스템암호화 방식
FairPlay (Apple)cbcs (AES-CBC + samples)
Widevine (Google)cenc 또는 cbcs
PlayReady (Microsoft)cenc 또는 cbcs

암호화 방식이 다르면 동일한 파일을 여러 DRM에서 못 쓴다.


CENC의 등장

Common Encryption (CENC)는 암호화 방식을 표준화한 ISO 규격이다.

CENC가 정의하는 두 방식:

cenc  (AES-CTR 모드)
cbcs  (AES-CBC + sample 단위)

CMAF는 이 중 cbcs를 권장한다. 모든 주요 DRM이 cbcs를 지원하기 때문이다.


CMAF + CENC의 효과

같은 CMAF 파일을 FairPlay, Widevine, PlayReady에서 모두 재생 가능하다.

원본 영상
  → CMAF + cbcs 암호화 (한 벌)
  → 라이선스만 DRM별로 발급

이전에는 DRM마다 별도 인코딩 + 별도 저장. 이제는 한 벌 + 라이선스 분리.


7.9 전체 흐름 정리

지금까지의 흐름을 정리하면 이렇다.

[HLS]
  안정성을 위해 설계됨
  → 구조 때문에 지연 발생

[5장: 지연 분석]
  encoder + segment + polling + buffer

[6장: LL-HLS]
  → "만들면서 전달하자"
  → Part, Blocking Reload, Preload Hint

[하지만 TS로는 구현 불가]
  → 데이터가 흐름 형태

[7장: fMP4 도입]
  → 독립 디코딩 가능한 조각 구조
  → 그러나 호환성 문제

[CMAF 표준화]
  → 쪼개는 단위 통일
  → 전송 방식 표준화
  → HLS와 DASH 호환
  → CENC로 DRM까지 통합

이 흐름의 끝에 우리가 있다.


비교표

구분기존 HLSLL-HLS + CMAF
컨테이너MPEG-TSfMP4 (CMAF)
전송 단위Segment 전체Chunk 즉시
응답 방식일반 HTTPChunked Transfer
호환 표준HLS 전용HLS + DASH 공통
암호화AES-128CENC (cbcs)
일반적 지연6~10초1~3초

7장 한 줄 정리

CMAF는 새로운 기술이 아니라 fMP4를 “어떻게 쓸지“를 약속한 규칙이며, 그 덕분에 데이터가 HLS와 DASH의 경계를 넘는다.